

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

/**
 * @author yiwen zhong
 *
 */
public class Solution implements Comparable<Solution> {

	public Solution(boolean initial) {
		problem = Problem.get();
		match = new int[problem.getItemNumber()];
		if ( initial ) { 
			densityList = problem.getDensityList();
			valueList = problem.getValueList();
			this.randPick(); 
		}
	}

	/**
	 * Use parameter to clone a new Solution
	 * 
	 * @param solution
	 */
	public Solution(Solution solution) {
		problem = Problem.get();
		match = solution.match.clone(); 
		lastImproving = solution.lastImproving;
		isValid = solution.isValid;
		value = solution.value;
		weight = solution.weight;
	}
	
	
	/**
	 * Use parameter to update this object
	 * 
	 * @param s
	 */
	public void update(Solution s) {
		for (int i = 0; i <match.length; i++) {
			match[i] = s.match[i];
		}
		lastImproving = s.lastImproving;
		isValid = s.isValid;
		value = s.value;
		weight = s.weight;
	}

	/*
	 * This method randomly selects items into knapsack
	 */
	private void randPick() {
		for (int i = 0; i < match.length; i++) {
			if (Solution.rand.nextDouble() < 0.5)  {
				match[i] = 1;
			} else {
				match[i] = 0;
			}
		}
		evalWithGreedyRepair();
		if (Simulation.useOptimization) optimization(Solution.densityList);
	}
	
	public void evalWithGreedyRepair() {
		int[] items = problem.getDensityOrder();
		double capacity = problem.getCapacity();
		value = 0;
		weight = 0;;
		//--------------------------------------------------
		System.out.println("To be implemented in evalWithGreedyRepair()!");
		System.exit(1);
		//--------------------------------------------------
		isValid = weight <= problem.getCapacity();
	}


	/**
	 * try to add items into knapsack
	 */
	public void optimization(List<Integer> itemList) {
		//--------------------------------------------------
		System.out.println("To be implemented in optimization()!");
		System.exit(1);
		//--------------------------------------------------
	}


	/**
	 * Produce a random neighbor
	 * 
	 * @return
	 */
	public Solution neighbor() {
		Solution s = new Solution(this);
		//-------------------------------------------------------
		System.out.println("To be implemented in neighbor()!");
		System.exit(1);
		//------------------------------------------------------
		s.evalWithGreedyRepair();
		if (Simulation.useOptimization) {
			if (Solution.rand.nextDouble() <= Simulation.densityProb) {
				s.optimization(Solution.densityList);
			} else {
				s.optimization(Solution.valueList);
			}
		}
		return s;
	}
	
	/* (non-Javadoc)
	 * @see java.lang.Comparable#compareTo(java.lang.Object)
	 */
	@Override
	public int compareTo(Solution s) {
		if ( value > s.value) {
			return 1;
		} else if ( value == s.value) {
			return 0;
		} else {
			return -1;
		}
	}

	public String toString() {
		String str = "";
        str += value + "," + weight + "\r\n";
        for (int i = 0; i < match.length; i++) {
        	str += match[i] + ",";
        }
        str += "\r\n";
        for (int i = 0; i < match.length; i++) {
        	str +=problem.getItemValue(i) + ",";
        }
		return str;
	}
	

	public int getItemNumber() { return match.length; }
	public List<Integer> getValueList() { return valueList;}
	public double getValue() {return value;}
	public double getWeight() { return weight;}
	public void setLastImproving(int n) { this.lastImproving = n; }
	public int getLastImproving() { return lastImproving;}

	private Problem problem;
	private int[] match;
	private double value;
	private boolean isValid;
	private double weight;
	private int lastImproving = 0; //
	
    private static List<Integer> densityList;
    private static List<Integer> valueList;
 
	public static void main(String[] args) {
		String filePath = (new File("")).getAbsolutePath() + "/datas/KP9/"; 
		String fileName = filePath+"kp1.txt";
		Problem.load(fileName);
		int times = 100;
		double[] values = new double[times];
		for (int i = 0; i < times; i++) {
			Solution s = new Solution(true);
			System.out.println(i + "--" + Problem.get().getBestValue() + ", " + s.value);
			values[i] = s.value;
		}
		System.out.println("Best: " + Tools.getMax(values) + ", Worst: " + Tools.getMin(values) + ", Mean: " + Tools.getMean(values));
	}

	private static Random rand = new Random();
}
